package loads

import (
	"jvm/instructions/base"
	"jvm/rtda"
	. "jvm/typedef"
)

// 从局部变量表指定的索引处加载元素推入操作数栈中，
// 索引由操作码自带或操作数给出。
// *****************************************************************
// iload_x操作通用函数
func iload(frame *rtda.Frame, index U2) {
	localVars := frame.LocalVars()
	stack := frame.OPStack()
	val := localVars.GetInt(index)
	stack.PushInt(val)
}

// *****************************************************************
type ILOAD struct {
	base.U1IndexInst
}

func (self *ILOAD) Execute(frame *rtda.Frame) {
	iload(frame, self.Index)
}

// *****************************************************************
type ILOAD_0 struct {
	base.NoOperandsInst
}

func (self *ILOAD_0) Execute(frame *rtda.Frame) {
	iload(frame, 0)
}

// *****************************************************************
type ILOAD_1 struct {
	base.NoOperandsInst
}

func (self *ILOAD_1) Execute(frame *rtda.Frame) {
	iload(frame, 1)
}

// *****************************************************************
type ILOAD_2 struct {
	base.NoOperandsInst
}

func (self *ILOAD_2) Execute(frame *rtda.Frame) {
	iload(frame, 2)
}

// *****************************************************************
type ILOAD_3 struct {
	base.NoOperandsInst
}

func (self *ILOAD_3) Execute(frame *rtda.Frame) {
	iload(frame, 3)
}

// *****************************************************************
// lload_x操作通用函数
func lload(frame *rtda.Frame, index U2) {
	localVars := frame.LocalVars()
	stack := frame.OPStack()
	val := localVars.GetLong(index)
	stack.PushLong(val)
}

// *****************************************************************
type LLOAD struct {
	base.U1IndexInst
}

func (self *LLOAD) Execute(frame *rtda.Frame) {
	lload(frame, self.Index)
}

// *****************************************************************
type LLOAD_0 struct {
	base.NoOperandsInst
}

func (self *LLOAD_0) Execute(frame *rtda.Frame) {
	lload(frame, 0)
}

// *****************************************************************
type LLOAD_1 struct {
	base.NoOperandsInst
}

func (self *LLOAD_1) Execute(frame *rtda.Frame) {
	lload(frame, 1)
}

// *****************************************************************
type LLOAD_2 struct {
	base.NoOperandsInst
}

func (self *LLOAD_2) Execute(frame *rtda.Frame) {
	lload(frame, 2)
}

// *****************************************************************
type LLOAD_3 struct {
	base.NoOperandsInst
}

func (self *LLOAD_3) Execute(frame *rtda.Frame) {
	lload(frame, 3)
}

// *****************************************************************
// fload_x操作通用函数
func fload(frame *rtda.Frame, index U2) {
	localVars := frame.LocalVars()
	stack := frame.OPStack()
	val := localVars.GetFloat(index)
	stack.PushFloat(val)
}

// *****************************************************************
type FLOAD struct {
	base.U1IndexInst
}

func (self *FLOAD) Execute(frame *rtda.Frame) {
	fload(frame, U2(self.Index))
}

// *****************************************************************
type FLOAD_0 struct {
	base.NoOperandsInst
}

func (self *FLOAD_0) Execute(frame *rtda.Frame) {
	fload(frame, 0)
}

// *****************************************************************
type FLOAD_1 struct {
	base.NoOperandsInst
}

func (self *FLOAD_1) Execute(frame *rtda.Frame) {
	fload(frame, 1)
}

// *****************************************************************
type FLOAD_2 struct {
	base.NoOperandsInst
}

func (self *FLOAD_2) Execute(frame *rtda.Frame) {
	fload(frame, 2)
}

// *****************************************************************
type FLOAD_3 struct {
	base.NoOperandsInst
}

func (self *FLOAD_3) Execute(frame *rtda.Frame) {
	fload(frame, 3)
}

// *****************************************************************
// dload_x操作通用函数
func dload(frame *rtda.Frame, index U2) {
	localVars := frame.LocalVars()
	stack := frame.OPStack()
	val := localVars.GetDouble(index)
	stack.PushDouble(val)
}

// *****************************************************************
type DLOAD struct {
	base.U1IndexInst
}

func (self *DLOAD) Execute(frame *rtda.Frame) {
	dload(frame, U2(self.Index))
}

// *****************************************************************
type DLOAD_0 struct {
	base.NoOperandsInst
}

func (self *DLOAD_0) Execute(frame *rtda.Frame) {
	dload(frame, 0)
}

// *****************************************************************
type DLOAD_1 struct {
	base.NoOperandsInst
}

func (self *DLOAD_1) Execute(frame *rtda.Frame) {
	dload(frame, 1)
}

// *****************************************************************
type DLOAD_2 struct {
	base.NoOperandsInst
}

func (self *DLOAD_2) Execute(frame *rtda.Frame) {
	dload(frame, 2)
}

// *****************************************************************
type DLOAD_3 struct {
	base.NoOperandsInst
}

func (self *DLOAD_3) Execute(frame *rtda.Frame) {
	dload(frame, 3)
}

// *****************************************************************
// aload_x操作通用函数
func aload(frame *rtda.Frame, index U2) {
	localVars := frame.LocalVars()
	stack := frame.OPStack()
	val := localVars.GetRef(index)
	stack.PushRef(val)
}

// *****************************************************************
type ALOAD struct {
	base.U1IndexInst
}

func (self *ALOAD) Execute(frame *rtda.Frame) {
	aload(frame, U2(self.Index))
}

// *****************************************************************
type ALOAD_0 struct {
	base.NoOperandsInst
}

func (self *ALOAD_0) Execute(frame *rtda.Frame) {
	aload(frame, 0)
}

// *****************************************************************
type ALOAD_1 struct {
	base.NoOperandsInst
}

func (self *ALOAD_1) Execute(frame *rtda.Frame) {
	aload(frame, 1)
}

// *****************************************************************
type ALOAD_2 struct {
	base.NoOperandsInst
}

func (self *ALOAD_2) Execute(frame *rtda.Frame) {
	aload(frame, 2)
}

// *****************************************************************
type ALOAD_3 struct {
	base.NoOperandsInst
}

func (self *ALOAD_3) Execute(frame *rtda.Frame) {
	aload(frame, 3)
}
